package com.kartoshka.managers 
{
	import com.kartoshka.debug.Console;
	import com.kartoshka.interfaces.IValidatable;

	import flash.events.EventDispatcher;
	import flash.events.Event;
	import flash.display.Stage;

	/**
	 * @author Alexander Zats, 2009
	 */
	public class ValidationManager extends EventDispatcher 
	{
		public static const FORCE : int = 1024;
		
		public static const STYLE : int = 1;
		public static const CHROME : int = 2;
		public static const CHILDREN : int = 4;
		public static const MEASUREMENT : int = 8;
		
		public static const ALL : int = STYLE | CHROME | CHILDREN | MEASUREMENT;

		private var _stage : Stage;
		private var _queue : Array;
		private var _isQueueBusy : Boolean;

		protected var _resizeTriggerImmediateValidation : Boolean;

		public function ValidationManager( lock : Lock )
		{
			if ( ! lock ) throw new Error( "This class can't be instaniated directly, you should reference to the ValidationManager.instance property instead!" );
			_queue = [];
		}

		public function addToQueue( instance : IValidatable ) : void
		{
			if ( ! _stage && ! instance.stage ) throw new Error( "No stage specified." );
			if ( ! _stage ) _stage = instance.stage;
			if ( _queue.indexOf( instance ) > - 1 ) 
			{
				Console.reportMessage( "Instance " + instance + " already in validation queue." );
				return;
			}
			_queue[ _queue.length ] = instance;
			Console.reportMessage( "Instance " + instance + " added to queue." );
			if ( _isQueueBusy )
			{
				Console.reportMessage( "Validation queue is busy." );
				return;
			}
			Console.reportMessage( "Invalidation triggered." );
			_stage.addEventListener( Event.RENDER, doValidation, false, 0, true );
			_stage.invalidate( );
		}

		private function doValidation( event : Event ) : void
		{
			_stage.removeEventListener( Event.RENDER, doValidation, false );
			_isQueueBusy = true;
			var item : IValidatable;
			Console.reportMessage( "" );
			while ( _queue.length )
			{
				item = _queue.pop( );
				Console.reportMessage( "Validating " + item );
				item.validate( );
			}
			Console.reportMessage( "" );
			_isQueueBusy = false;
		}

		public function set resizeTriggerImmediateValidation( value : Boolean ) : void
		{
			if ( value == _resizeTriggerImmediateValidation ) return;
			_resizeTriggerImmediateValidation = value;
			this.dispatchEvent( new Event( "resizeTriggerImmediateValidationChanged" ) );
		}

		public function get resizeTriggerImmediateValidation() : Boolean
		{
			return _resizeTriggerImmediateValidation;
		}

		public static function set resizeTriggerImmediateValidation( value : Boolean ) : void
		{
			ValidationManager.instance.resizeTriggerImmediateValidation = value;
		}

		public static function get resizeTriggerImmediateValidation() : Boolean
		{
			return ValidationManager.instance.resizeTriggerImmediateValidation;
		}

		private static var _instance : ValidationManager;

		public static function get instance() : ValidationManager
		{
			if ( ! _instance ) _instance = new ValidationManager( new Lock( ) );
			return _instance;
		}
	}
}

class Lock
{
}